import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.MultiSearchResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.FieldSortBuilder;

import java.util.Map;

/**
 * Created by xi on 2016/12/7.
 */
public class OpManager {

    //添加一个文档
    public static void singleAddDoc(Client client,String indexName,String type,String id,String jsonData){
        IndexResponse response =  client.prepareIndex(indexName, type)
                .setSource(jsonData)
                .setId(id)
                        //.setId(jsonData.getString(KEY))//自己设置了id，也可以使用ES自带的，但是看文档说，ES的会因为删除id发生变动。
                .execute()
                .actionGet();
        System.out.println("singleAddDoc:"+response.toString());
//        IndexResponse response = client.prepareIndex("twitter", "tweet")
//                .setSource(jsonData)
//                .get();
    }

    //批量添加文档
    public static void multiAddDoc(Client client,String indexName,String type,String jsonData){
        BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();

        for (int i = 0; i < 10; i++){
            bulkRequestBuilder.add(client.prepareIndex(indexName, type)
                    .setSource(jsonData));
        }
        BulkResponse bulkResponse = bulkRequestBuilder.execute().actionGet();
        bulkRequestBuilder.request().requests().clear();
        if (bulkResponse.hasFailures()){
            //TODO:
        }
    }

    /**
     * TODO 根据主键查询单条记录********************************
     *
     * @param indexName 索引名称
     * @param type      索引类型
     * @return
     */
    public Map<String, Object> getSingleRecordByPrimaryKey(Client client,String indexName, String type, String primaryKey) {
        GetResponse searchResponse = client.prepareGet(indexName, type, primaryKey)
                .setOperationThreaded(false)
                .execute()
                .actionGet();
        return searchResponse.getSource();
    }

    //获取一个文档
    public static String getOneDoc(Client client,String indexName,String type,String id){
        GetResponse response = client.prepareGet(indexName,type,id).get();
        return response.getSourceAsString();
    }

    //搜索查询
    public static void search(Client client,String indexName,String type){
//        SearchRequestBuilder srb1 = client
//                .prepareSearch().setQuery(QueryBuilders.queryStringQuery("elasticsearch")).setFrom(0).setSize(100);
        QueryBuilder m1 = QueryBuilders.termQuery("name", "xiaocai");
        //QueryBuilder m2 = QueryBuilders.termQuery("time", "2L");//如果返回的是字符串，但是索引的是long类型，这里匹配不上；
        QueryBuilder m3 = QueryBuilders.termQuery("time", 2L);
        QueryBuilder m4 = QueryBuilders.termQuery("email", "93");
        BoolQueryBuilder boolQueryBuilder =   QueryBuilders.boolQuery();
        boolQueryBuilder.must(m1).should(m4);//这种查询不行，只会查询must的匹配

        //必须外面套一层must
        BoolQueryBuilder totalQuery = QueryBuilders.boolQuery();
        totalQuery.must(boolQueryBuilder);

        SearchRequestBuilder srb2 = client
                .prepareSearch().setQuery(totalQuery).setSize(1);

        System.out.println("search;"+srb2.toString());

        MultiSearchResponse sr = client.prepareMultiSearch()
               // .add(srb1)
                .add(srb2)
                .get();
      // You will get all individual responses from MultiSearchResponse#getResponses()
        long nbHits = 0;
        System.out.println("sr:"+sr.getResponses().length);
        for (MultiSearchResponse.Item item : sr.getResponses()) {
            SearchResponse response = item.getResponse();
            System.out.println("sr:"+sr.getResponses().length);
            System.out.println("response:"+response);
            SearchHits hits = response.getHits();
            long record = 0;
            long totalCount = hits.getHits().length;
            long allCount = hits.totalHits();
            System.out.println("totalCount:"+totalCount+",allCount="+allCount);
            for (int i = 0; i < totalCount; i++) {
                Map map = hits.getAt(i).getSource();
                System.out.println("result:"+map.get("name"));
            }
            nbHits += response.getHits().getTotalHits();
        }
        System.out.println(nbHits);
    }


    /**
     *在布尔查询中，各个子句之间的逻辑关系是与（and)
     *
     * 如果总文档存在这AOrB，那么外层就最好都是should组合；
     * 如果总文档是A and B(1 or 2 or 3) 那么外层最好是must组合；
     * must(A).must(Boolquyer.should(1).should(2).should(3)) 这样 1,2,3 种至少满足一个并且A通过，就成功；
     *
     * //不要使用这种组合方式,这种是A and (B{0,+})方式，这种只要A满足条件，Ｂ　不满足都能搜索到
     * Boolquyer.must(A).should(B);
     *
     * @param client
     * @param indexName
     * @param type
     */
    public static void searchBySelfClasss(Client client,String indexName,String type){
//        SearchRequestBuilder srb1 = client
//                .prepareSearch().setQuery(QueryBuilders.queryStringQuery("elasticsearch")).setFrom(0).setSize(100);
        QueryBuilder m1 = QueryBuilders.termQuery("name", "xiaocai");
        //QueryBuilder m2 = QueryBuilders.termQuery("time", "2L");//如果返回的是字符串，但是索引的是long类型，这里匹配不上；
        QueryBuilder m3 = QueryBuilders.termQuery("time", 2L);
        QueryBuilder m4 = QueryBuilders.termQuery("email", "933");
        BoolQueryBuilder s1 =  QueryBuilders.boolQuery();
       // s1.must(m1).should(m4);//A and ( m4 {0,+}) 在布尔查询中，各个子句之间的逻辑关系是与（and）。 m3可以出现0次或者以上，但是m1一定要成功
        //m1成功，m4不成功，result:能查到数据，
        //s1.must(m1).should(m4).minimumShouldMatch(1);//minimum_should_match 默认是0 m1，m4 不满足 result:查询不到数据
        s1.must(m1).must(QueryBuilders.boolQuery().should(m4).minimumShouldMatch("1"));//must的m4必须满足和m1满足才有数据成功

        //必须外面套一层must
        BoolQueryBuilder totalQuery = QueryBuilders.boolQuery();
        //totalQuery
        //should 至少一个满足条件有结果了
        //totalQuery.should(QueryBuilders.boolQuery().must(m1)).should(QueryBuilders.boolQuery().must(m4)).minimumShouldMatch(0);

        totalQuery.must(s1);

        //FuzzyQuery是一种模糊查询，它可以简单地识别两个相近的词语。 即相似度匹配
        //能查询出xiaocai的数字相当于模糊查询

        //totalQuery.must(QueryBuilders.fuzzyQuery("name","xiaoca"));

        //totalQuery.must(new FuzzyQueryBuilder());
//        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
//                .must(QueryBuilders.termQuery("name", "xiaocai"))
//                .mustNot(QueryBuilders.termQuery("time", 1L))
//                .should(QueryBuilders.termQuery("email", "93"));


        //must和should结合外面必须套个must
        SearchRequestBuilder srb2 = client
                .prepareSearch().setQuery(totalQuery).setSize(10);

        System.out.println("search;"+srb2.toString());

        MultiSearchResponse sr = client.prepareMultiSearch()
                // .add(srb1)
                .add(srb2)
                .get();
        // You will get all individual responses from MultiSearchResponse#getResponses()
        long nbHits = 0;
        System.out.println("sr:"+sr.getResponses().length);
        for (MultiSearchResponse.Item item : sr.getResponses()) {
            SearchResponse response = item.getResponse();
            System.out.println("sr:"+sr.getResponses().length);
            System.out.println("response:"+response);
            SearchHits hits = response.getHits();
            long record = 0;
            long totalCount = hits.getHits().length;
            long allCount = hits.totalHits();
            System.out.println("totalCount:"+totalCount+",allCount="+allCount);
            for (int i = 0; i < totalCount; i++) {
                Map map = hits.getAt(i).getSource();
                System.out.println("result:"+map.get("name"));
            }
            nbHits += response.getHits().getTotalHits();
        }
        System.out.println(nbHits);
    }


    //搜索查询
    public static void searchOrder(Client client,String indexName,String type){
//        SearchRequestBuilder srb1 = client
//                .prepareSearch().setQuery(QueryBuilders.queryStringQuery("elasticsearch")).setFrom(0).setSize(100);
        QueryBuilder builder =  QueryBuilders.queryStringQuery("住宅").defaultField("usageType");
        QueryBuilder builder1 =  QueryBuilders.commonTermsQuery("usageType", "住宅");
        QueryBuilder builder12 = QueryBuilders.termQuery("tradeStatus", "有效");

        QueryBuilder builder3 =  QueryBuilders.termQuery("propertyId",390168);
        QueryBuilder builder31 = QueryBuilders.termQuery("estateName","上南三村");

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(builder12);

        SearchRequestBuilder searchBuilder = client
                .prepareSearch(indexName).setQuery(boolQueryBuilder).setFrom(0).setSize(1000);
        //searchBuilder.addSort("focusProperty", SortOrder.DESC);
        MultiSearchResponse sr = client.prepareMultiSearch()
                // .add(srb1)
                .add(searchBuilder)
                .get();

        // You will get all individual responses from MultiSearchResponse#getResponses()
        long nbHits = 0;
        for (MultiSearchResponse.Item item : sr.getResponses()) {
            SearchResponse response = item.getResponse();
            SearchHits hits = response.getHits();;
            long totalCount = hits.getHits().length;
            long allCount = hits.totalHits();
            System.out.println("totalCount:"+totalCount+",allCount="+allCount);
            for (int i = 0; i < totalCount; i++) {
                Map map = hits.getAt(i).getSource();
                System.out.println("tradeStatus:"+map.get("tradeStatus"));
            }
            nbHits += response.getHits().getTotalHits();
        }
        System.out.println(nbHits);
    }

    //missing 过滤器本质上是 exists 的逆：它返回对应一个特定的字段没有任何值的文档，就像 SQL：
    //WHERE tags IS NULL

    //"_source" : { "other_field" : "some data" }  "_source" : { "tags" : null }
    //totalCount:89,allCount=89

    //existsQuery 表示有值，为空不会出来的。
    //mustNot existsQuery 代表不存在这个方案
    public static void searchNullValue(Client client,String indexName,String type){
        QueryBuilder builder12 =  QueryBuilders.existsQuery("employee2Py");
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(builder12);

        SearchRequestBuilder searchBuilder = client.prepareSearch(indexName).setQuery(boolQueryBuilder).setFrom(0).setSize(1000);
        //searchBuilder.addSort("focusProperty", SortOrder.DESC);
        MultiSearchResponse sr = client.prepareMultiSearch()
                // .add(srb1)
                .add(searchBuilder)
                .get();

        // You will get all individual responses from MultiSearchResponse#getResponses()
        long nbHits = 0;
        for (MultiSearchResponse.Item item : sr.getResponses()) {
            SearchResponse response = item.getResponse();
            SearchHits hits = response.getHits();;
            long totalCount = hits.getHits().length;
            long allCount = hits.totalHits();
            System.out.println("totalCount:"+totalCount+",allCount="+allCount);
            for (int i = 0; i < totalCount; i++) {
                Map map = hits.getAt(i).getSource();
                System.out.println("tradeStatus:"+map.get("propertyId")+",py:"+map.get("employee2Py"));
            }
            nbHits += response.getHits().getTotalHits();
        }
        System.out.println(nbHits);

    }
}
